const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const startTagClose = /^\s*(\/?)>/
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g

// 解析html
export function parseHTML(html) {
    const ELEMENT_TYPE = 1;
    const TEXT_TYPE = 3;
    const stack = []; //用于定位父子关系
    let currentParent; //永远指向栈中最后一个
    let root; //根节点
    function createASTElement(tag, attrs) {
        return {
            tag,
            type: ELEMENT_TYPE,
            children: [],
            attrs,
            parent: null
        };
    }

    function start(tag, attrs) {
        let node = createASTElement(tag, attrs)
        if (!root) {
            root = node;
        }
        // div
        // div span _> span.parent = div
        if (currentParent) {
            node.parent = currentParent;
            currentParent.children.push(node);
        }
        stack.push(node);
        currentParent = node;
    }

    function chars(text) { //文本直接放入当前节点中
        text = text.replace(/\s/g, '');
        text && currentParent.children.push({
            type: TEXT_TYPE,
            text,
            parent: currentParent
        });
    }

    function end(tag) {
        // 弹出
        stack.pop();
        currentParent = stack[stack.length - 1];
    }


    // 前进
    function advance(len) {
        html = html.substring(len);
    }

    // 开始匹配
    function parseStartTag() {
        const start = html.match(startTagOpen); // 0：开始标签，1：标签名
        if (start) {
            const match = {
                tagName: start[1],
                attrs: []
            };
            advance(start[0].length)
            // 匹配属性，只要不是开始开始标签的结束符合就一直匹配
            let attr;
            let end;
            while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
                advance(attr[0].length);
                match.attrs.push({name: attr[1], value: attr[3] || attr[4] || attr[5]});
            }
            if (end) {
                advance(end[0].length)
            }
            return match;
        }

        return false;
    }

    while (html) {
        let textEnd = html.indexOf("<")
        //     textEnd = 0 开始或者结束 >0 文本结束
        if (textEnd === 0) {
            const startMatch = parseStartTag()
            if (startMatch) {
                start(startMatch.tagName, startMatch.attrs)
                continue;
            }
            let endTagMatch = html.match(endTag)
            if (endTagMatch) {
                advance(endTagMatch[0].length)
                end(endTagMatch[1])
                continue;
            }
        }
        if (textEnd > 0) {
            //     截取文本
            let text = html.substring(0, textEnd);
            if (text) {
                chars(text);
                advance(text.length);
            }
        }

    }
    return root;
}